package baseRpc

import (
	"gitee.com/zaiqiang231/go-base-app/base_app"
	baseLog "gitee.com/zaiqiang231/go-base-app/base_app/log"
	"golang.org/x/sync/errgroup"
	"google.golang.org/grpc"
	"net"
)

type GrpcServer struct {
	basename string
	gs       *base_app.GracefulShutdown
	*grpc.Server
	address string
}

type ServerOption func(*GrpcServer)

func WithAddress(address string) ServerOption {
	return func(server *GrpcServer) {
		server.address = address
	}
}

func WithGracefulShutdown(gs *base_app.GracefulShutdown) ServerOption {
	return func(server *GrpcServer) {
		server.gs = gs
	}
}

type InitGRpcFunc func(server *GrpcServer)

//use cmd : protoc --go_out=plugins=grpc:. *.proto

func WithGRpcServer(initFunc InitGRpcFunc) ServerOption {
	return func(server *GrpcServer) {
		initFunc(server)
	}
}

func CreateGrpcServer(basename string, opts ...ServerOption) *GrpcServer {
	server := &GrpcServer{
		basename: basename,
	}

	for _, opt := range opts {
		opt(server)
	}

	return server
}

func (s *GrpcServer) PrepareRun() *GrpcServer {
	s.gs.AddShutdownCallback(base_app.ShutdownFunc(func() error {
		baseLog.Debugf("%v api server start shutdown", s.basename)
		s.GracefulStop()
		return nil
	}))
	return s
}

func (s *GrpcServer) Run(eg *errgroup.Group) {
	eg.Go(func() error {
		listen, err := net.Listen("tcp", s.address)
		if err != nil {
			baseLog.Fatalf("%s failed to listen: %s", s.basename, err.Error())
		}

		if err := s.Serve(listen); err != nil {
			baseLog.Fatalf("%s failed to start grpc server: %s", s.basename, err.Error())
		}
		return nil
	})
}
